from contextlib import asynccontextmanager

from fastapi import FastAPI, Request

from config.env import AppConfig
from config.get_db import init_create_table
# 确保所有模型类在表创建前被导入（这样Base.metadata才会包含它们）
from module_admin.entity.do.search_record_do import SearchRecord  # noqa: F401
from config.get_redis import RedisUtil
from config.get_scheduler import SchedulerUtil
from exceptions.handle import handle_exception
from mcp_server.ai_websocket import init_ai_websocket
from middlewares.handle import handle_middleware
from router import router_manager
from sub_applications.handle import handle_sub_applications
from utils.common_util import worship
from utils.log_util import logger


# 生命周期事件
@asynccontextmanager
async def lifespan(app: FastAPI):
    logger.info(f'{AppConfig.app_name}开始启动')
    worship()
    await init_create_table()
    app.state.redis = await RedisUtil.create_redis_pool()
    await RedisUtil.init_sys_dict(app.state.redis)
    await RedisUtil.init_sys_config(app.state.redis)
    await SchedulerUtil.init_system_scheduler()
    # await init_ai_websocket(app)

    # 启动TCP服务器和心跳监控
    from tcp_server.tcp_server import tcp_server
    from tcp_server.heartbeat_monitor import get_heartbeat_monitor
    from config.database import AsyncSessionLocal
    
    # 设置数据库会话和Redis
    tcp_server.set_db_session(AsyncSessionLocal)
    tcp_server.set_redis(app.state.redis)
    
    # 启动心跳监控（超时90秒，每30秒检查一次）
    heartbeat_monitor = get_heartbeat_monitor(AsyncSessionLocal)
    await heartbeat_monitor.start()
    
    # 在后台启动TCP服务器
    import asyncio
    tcp_task = asyncio.create_task(tcp_server.start_server())
    logger.info("TCP服务器启动任务已创建")
    
    # 挂载子应用
    handle_sub_applications(app)
    logger.info(f'{AppConfig.app_name}启动成功')
    yield
    
    # 关闭TCP服务器和心跳监控
    logger.info("正在关闭TCP服务器和心跳监控...")
    await heartbeat_monitor.stop()
    await tcp_server.stop_server()
    tcp_task.cancel()
    try:
        await tcp_task
    except asyncio.CancelledError:
        pass
    
    await RedisUtil.close_redis_pool(app)
    await SchedulerUtil.close_system_scheduler()
    logger.info("所有服务已关闭")


# 初始化FastAPI对象
# ⚠️ 问题：当设置了 root_path 时，Swagger UI 会基于 root_path 构建 openapi.json 的 URL
# 解决方案：不设置 root_path，而是通过中间件处理路径重写
# 或者：使用 X-Forwarded-Prefix 头来让 Swagger UI 知道原始路径
app = FastAPI(
    title=AppConfig.app_name,
    description=f'{AppConfig.app_name}接口文档',
    version=AppConfig.app_version,
    lifespan=lifespan,
    root_path=AppConfig.app_root_path,
    # ✅ 使用绝对路径，包含 root_path，这样 Swagger UI 能正确找到 openapi.json
    # 无论通过 /server/docs 还是 /dev-api/docs 访问，都会使用 /dev-api/openapi.json
    openapi_url=f"{AppConfig.app_root_path}/openapi.json",
    docs_url=f"{AppConfig.app_root_path}/docs",
    redoc_url=f"{AppConfig.app_root_path}/redoc",
)


# 定义中间件
@app.middleware("http")
async def block_post_requests(request: Request, call_next):
    # 检查请求方法是否为 POST
    # if request.url.path not in ("/logout", "/login") and request.method in ("POST", "PUT", "PATCH", "DELETE"):
    #     return ResponseUtil.error(msg="演示环境，暂不允许修改数据")
    # 继续处理其他请求
    response = await call_next(request)
    return response


# ✅ 已移除复杂的路径修复中间件
# 现在统一使用 /dev-api 路径，不再需要路径重写和修复

# 加载中间件处理方法
handle_middleware(app)
# 加载全局异常处理方法
handle_exception(app)

# 加载路由列表
app.include_router(router_manager.register_router())

